package com.stud.system.util;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.stud.system.dto.AreaDTO;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;

/**
 * @author Stud
 * @title XXXXX
 * @desription XXXXX
 * @data 2022-09-27 18:31
 */

public class AreaUtil {

    /**
     * 根据idList计算最小树
     *
     * @param fullList
     * @param idList
     * @return
     */
    public static List<AreaDTO> minTree(List<AreaDTO> fullList, List<Long> idList) {
        if (CollectionUtils.isEmpty(fullList) || CollectionUtils.isEmpty(idList)) {
            return Lists.newArrayList();
        }
        List<AreaDTO> list = Lists.newArrayList();

        Map<Long, AreaDTO> id2Area = Maps.newHashMap();

        for (AreaDTO areaDTO : fullList) {
            id2Area.put(areaDTO.getId(), areaDTO);
        }

        for (Long areaId : idList) {
            if (id2Area.containsKey(areaId)) {
                AreaDTO temp = id2Area.get(areaId);
                recurseUpForMinTree(temp, id2Area);
            }
        }

        for (AreaDTO areaDto : fullList) {
            if (areaDto.getLive()) {
                list.add(areaDto);
            }
        }

        return list;
    }

    /**
     * 计算树结构
     *
     * @param list 必须是树 第一个必须是root
     * @return
     */
    public static List<AreaDTO> initComposition(List<AreaDTO> list) {
        AreaDTO root = list.get(0);

        Map<Long, List<AreaDTO>> id2Children = Maps.newHashMap();
        Map<Long, AreaDTO> id2Area = Maps.newHashMap();
        for (AreaDTO temp : list) {
            id2Area.put(temp.getId(), temp);
            List<AreaDTO> children;
            if (id2Children.containsKey(temp.getParentId())) {
                children = id2Children.get(temp.getParentId());
            } else {
                children = Lists.newArrayList();
                id2Children.put(temp.getParentId(), children);
            }
            children.add(temp);
        }

        for (AreaDTO temp : list) {
            if (id2Area.containsKey(temp.getParentId())) {
                recurseUpForParent(temp, id2Area.get(temp.getParentId()), id2Area);
            }
        }

        if (id2Children.containsKey(root.getId())) {
            recurseDownAreaChildren(root, id2Children, id2Area);
        }

        return list;
    }

    private static void recurseUpForMinTree(AreaDTO areaDto, Map<Long, AreaDTO> id2Area) {
        areaDto.setLive(true);
        if (id2Area.containsKey(areaDto.getParentId())) {
            recurseUpForMinTree(id2Area.get(areaDto.getParentId()), id2Area);
        }
    }

    private static void recurseDownAreaChildren(AreaDTO areaDto, Map<Long, List<AreaDTO>> id2Children, Map<Long, AreaDTO> id2Area) {
        List<AreaDTO> children = id2Children.get(areaDto.getId());
        for (AreaDTO child : children) {
            if (id2Children.containsKey(child.getId())) {
                recurseDownAreaChildren(child, id2Children, id2Area);
            }
            areaDto.getChildrenIdList().add(child.getId());
            areaDto.getAllChildrenIdList().add(child.getId());
            if (id2Area.containsKey(areaDto.getParentId())) {
                recurseUpForAllChildren(id2Area.get(areaDto.getParentId()), id2Area, child.getId());
            }
        }
    }

    private static void recurseUpForAllChildren(AreaDTO areaDto, Map<Long, AreaDTO> id2Area, Long childId) {
        areaDto.getAllChildrenIdList().add(childId);
        if (id2Area.containsKey(areaDto.getParentId())) {
            recurseUpForAllChildren(id2Area.get(areaDto.getParentId()), id2Area, childId);
        }
    }

    private static void recurseUpForParent(AreaDTO areaDto, AreaDTO parent, Map<Long, AreaDTO> id2Area) {
        areaDto.getParentIdList().add(parent.getId());
        if (id2Area.containsKey(parent.getParentId())) {
            recurseUpForParent(areaDto, id2Area.get(parent.getParentId()), id2Area);
        }
    }
}




